using System;
using System.IO;
using Microsoft.Isam.Esent.Interop;

namespace Microsoft.Isam.Esent.Serialization.Attributes
{
	/// <summary>Column containing arbitrary binary data.</summary>
	/// <remarks>
	/// <para>Must be applied to a field/property of type '<see cref="ByteArray" />'.</para>
	/// <para>The underlying ESENT column type is JET_coltypLongBinary.</para>
	/// <para>Don't use it with items over few kilobytes: the whole value lives in RAM when deserialized.
	/// If you ever need handling megabytes-sized binary fields, use <see cref="EseBinaryStreamAttribute"/> instead.</para>
	/// </remarks>
	public class EseByteArrayAttribute : EseShortBinaryAttribute
	{
		/// <summary>Initialize with the default column name, which is the name of the field/property.</summary>
		public EseByteArrayAttribute() { maxBytes = 0; }
		/// <summary>Initialize with non-default column name.</summary>
		public EseByteArrayAttribute( string _columnName ) : base( _columnName ) { maxBytes = 0; }

		/// <summary>The maximum length, in KiloBytes, of a column.</summary>
		public double maxKB
		{
			get { return (double)( maxBytes ) / 1024.0; }
			set
			{
				if( value <= 0 || value > ( int.MaxValue / 1024 ) )
					throw new ArgumentOutOfRangeException( "value" );
				maxBytes = (int)( value * 1024.0 ); }
		}

		/// <summary>The maximum length, in MegaBytes, of a column.</summary>
		public double maxMB
		{
			get { return maxKB / 1024.0; }
			set { maxKB = value * 1024.0; }
		}

		/// <summary>Get column definition.</summary>
		public override JET_COLUMNDEF getColumnDef()
		{
			JET_COLUMNDEF res = new JET_COLUMNDEF();
			res.coltyp = JET_coltyp.LongBinary;
			res.grbit = ColumndefGrbit.ColumnTagged;
			res.cbMax = maxBytes;
			return res;
		}
	}

	/// <summary>Column containing long text, either ASCII of Unicode.</summary>
	/// <remarks>
	/// <para>Must be applied to a field/property of type 'string'.</para>
	/// <para>The underlying ESENT column type is JET_coltypLongText, either Unicode (which is the default), or ASCII.</para>
	/// <para>Please spare the memory manager, don't use it with items over few kilobytes,
	/// as the whole value lives in RAM as the System.String object.</para>
	/// </remarks>
	public sealed class EseLongTextAttribute : EseTextAttribute
	{
		/// <summary>Initialize with the default column name, which is the name of the field/property.</summary>
		public EseLongTextAttribute() { }
		/// <summary>Initialize with non-default column name.</summary>
		public EseLongTextAttribute( string _columnName ) : base( _columnName ) { }

		/// <summary>Get column definition.</summary>
		public override JET_COLUMNDEF getColumnDef()
		{
			JET_COLUMNDEF res = getTextBaseColumnDef();
			res.coltyp = JET_coltyp.LongText;
			res.grbit |= ColumndefGrbit.ColumnTagged;

			if( Params.bUseColumnCompressionIfAvailable )
			{
				var ver = Environment.OSVersion.Version;
				if( ver.Major > 6 || ( ver.Major == 6 && ver.Minor >= 1 ) )
					res.grbit |= Microsoft.Isam.Esent.Interop.Windows7.Windows7Grbits.ColumnCompressed;
			}

			return res;
		}

		/// <summary>Maximum text length, in characters.</summary>
		new public int maxChars { get { return m_maxChars; } set { m_maxChars = value; } }

		/// <summary>Throws NotSupportedException.</summary>
		new public bool _fixed { get { throw new NotSupportedException(); } set { throw new NotSupportedException(); } }
	}
}